package com.example.flowlayoutdemo1

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.ContextCompat

/**
 *  Created by renchunlin on 2022/8/8
 */
class FlowLayout : ViewGroup {

    val mData: MutableList<String> = arrayListOf()

    companion object {
        const val DEFAULT_LINE = 3

        //后面需要转单位，目前是px不适配
        const val DEFAULT_HORIZONTAL_MARGIN = 5f
        const val DEFAULT_VERTICAL_MARGIN = 5f
        const val DEFAULT_TEXT_MAX_LENGTH = 20
        const val DEFAULT_BORDER_RADIUS = 5
        const val TAG = "FlowLayout"
    }

    private var mMaxLines = 0
    private var mItemHorizontalMargin = 0f
    private var mItemVerticalMargin = 0f
    private var mTextMaxLength = 0
    private var mTextColor = 0
    private var mBorderColor = 0
    private var mBorderRadius = 0

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        //获取属性
        val typeArray = context!!.obtainStyledAttributes(attrs, R.styleable.FlowLayout)

        //maxLine
        mMaxLines = typeArray.getInt(R.styleable.FlowLayout_maxLine, DEFAULT_LINE)
        //itemHorizontalMargin
        mItemHorizontalMargin = typeArray.getDimension(
            R.styleable.FlowLayout_itemHorizontalMargin,
            DEFAULT_HORIZONTAL_MARGIN
        )
        //itemVerticalMargin
        mItemVerticalMargin = typeArray.getDimension(
            R.styleable.FlowLayout_itemVerticalMargin,
            DEFAULT_VERTICAL_MARGIN
        )
        //textMaxLength
        mTextMaxLength =
            typeArray.getInt(R.styleable.FlowLayout_textMaxLength, DEFAULT_TEXT_MAX_LENGTH)
        //textColor
        mTextColor = typeArray.getColor(
            R.styleable.FlowLayout_textColor,
            ContextCompat.getColor(context, R.color.text_grey)
        )
        //BorderColor
        mBorderColor = typeArray.getColor(
            R.styleable.FlowLayout_borderColor,
            ContextCompat.getColor(context, R.color.text_grey)
        )
        //BorderRadius
        mBorderRadius =
            typeArray.getColor(R.styleable.FlowLayout_borderRadius, DEFAULT_BORDER_RADIUS)

        /*Log.i(TAG, ": mMaxLines==>$mMaxLines")
        Log.i(TAG, ": mItemHorizontalMargin==>$mItemHorizontalMargin")
        Log.i(TAG, ": mItemVerticalMargin==>$mItemVerticalMargin")
        Log.i(TAG, ": mTextMaxLength==>$mTextMaxLength")
        Log.i(TAG, ": mTextColor==>$mTextColor")
        Log.i(TAG, ": mBorderColor==>$mBorderColor")
        Log.i(TAG, ": mBorderRadius==>$mBorderRadius")*/

        typeArray.recycle()
    }

    fun setTextList(data: MutableList<String>) {
        mData.clear()
        mData.addAll(data)
        //根据数据创建子View，并且添加进来
        setUpChildren()
    }

    private fun setUpChildren() {
        //先清空原来的数据
        removeAllViews()
        //添加子view进来
        for (mDatum in mData) {
            val textView = TextView(context)
            textView.text = mDatum
            //设置TextView的相关属性：边距，颜色，border之类
            addView(textView)

        }
    }

    //存有几行
    //MutableList<View>存每行的个数
    private val mLines: MutableList<MutableList<View>> = arrayListOf()

    /**
     * 这个两个值来父控件，包含值和模式，这里的父控件就是FlowLayout（this），当前类
     */
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val parentWidthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val parentHeightSize = MeasureSpec.getSize(heightMeasureSpec)

        /*Log.i(TAG, "widthMode==>$widthMode")
        Log.i(TAG, "widthSize==>$widthSize")*/

        //拿到孩子的个数
        val childCount = childCount
        //如果孩子为0不用往下算了，浪费资源
        if (childCount == 0) {
            return;
        }
        //先清空
        mLines.clear()
        //添加默认行
        var line: MutableList<View> = arrayListOf()
        mLines.add(line)
        val childWidthSpec = MeasureSpec.makeMeasureSpec(parentWidthSize, MeasureSpec.AT_MOST)
        val childHeightSpec = MeasureSpec.makeMeasureSpec(parentHeightSize, MeasureSpec.AT_MOST)
        for (i in 0 until childCount) {
            //拿到单独的一个孩子
            val child = getChildAt(i)
            //严谨判断
            if (child.visibility != View.VISIBLE) {
                continue
            }
            //测量孩子
            measureChild(child, childWidthSpec, childHeightSpec)
            if (line.size == 0) {
                //可以添加
                line.add(child)
            } else {
                //判断是否可以添加到当前行
                val canBeAdd = checkChildCanBeAdd(line, child, parentWidthSize)
                if (canBeAdd) {
                    line.add(child)
                } else {
                    line = arrayListOf()
                    mLines.add(line)
                }
            }
        }

        //根据尺寸计算所有行高
        val child = getChildAt(0)
        val measuredHeight = child.measuredHeight
        val parentHeightTargetSize = measuredHeight * mLines.size
        //测量自己(里面传宽高，宽高是不包含模式的)
        setMeasuredDimension(parentWidthSize, parentHeightTargetSize)
    }

    private fun checkChildCanBeAdd(
        line: MutableList<View>,
        child: View?,
        parentWidthSize: Int
    ): Boolean {
        //拿到单个子控件的宽度
        val measuredWidth = child?.measuredWidth
        var totalWidth = 0
        for (view in line) {
            totalWidth += view.measuredWidth
        }
        totalWidth += measuredWidth!!
        //如果超出限制宽度，则不可以再添加
        //否则可以添加
        return totalWidth <= parentWidthSize
    }

    override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int) {
        /*val childAt = getChildAt(0)
        childAt.layout(0, 0, childAt.measuredWidth, childAt.measuredHeight)

        val childAt1 = getChildAt(1)
        childAt1.layout(
            childAt.right,
            0,
            childAt.right + childAt1.measuredWidth,
            childAt1.measuredHeight
        )*/

        val firstChild = getChildAt(0)
        var currentLeft = 0
        var currentRight = 0
        var currentTop = 0
        var currentBottom = firstChild.measuredHeight
        for (mLine in mLines) {
            for (view in mLine) {
                //布局每一行
                currentRight += view.measuredWidth
                currentBottom += view.measuredHeight
                view.layout(currentLeft, currentTop, currentRight, currentBottom)
                currentLeft = currentRight
            }
            currentLeft = 0
            currentRight = 0
            currentBottom += firstChild.measuredHeight
            currentTop += firstChild.measuredHeight
        }
    }
}